package com.cavedroid;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

public class TiltGameThread extends GameThread implements SensorEventListener {
	
	protected static final float TILT_FIELD_SIZE = 30;
	
	protected static final float MAX_VERTICAL_VELOCITY = 1;
	
	SensorManager sensorManager;
	
	private float baseLine;
	
	private float verticalAngle;
	
	public float verticalDirection = 1;
	
	protected float[] orientation = new float[3];
	private float[] acceleration;
	private float[] magnetic;
	
	private float[] rotation = new float[16];
	private float[] inclination = new float[16];
	private float[] outputMatrix = new float[16];
	
	private boolean sensorReadingTaken;
	private boolean baseReadingTaken;

	public TiltGameThread(CaveViewActivity a) {
		super(a);
		obstacleFrequency = 2;
		sensorManager = (SensorManager) parentActivity.getSystemService(Activity.SENSOR_SERVICE);
	}

	@Override
	protected void readInput() {
		if (!SensorManager.getRotationMatrix(rotation, inclination, acceleration, magnetic)) {
			Log.d("Cavedroid", "Invalid acceleration");
		}
		
		if (!SensorManager.remapCoordinateSystem(rotation, SensorManager.AXIS_MINUS_X, SensorManager.AXIS_MINUS_Y, outputMatrix)) {
			Log.d("Cavedroid", "Invalid acceleration");
		}
		SensorManager.getOrientation(outputMatrix, orientation);
		
		verticalAngle = (float) Math.toDegrees(orientation[2]);
		
		float tilt = verticalAngle - baseLine;
		
		if (baseReadingTaken) {
			if (tilt > 0) {
				verticalVelocity = verticalDirection*Math.min(MAX_VERTICAL_VELOCITY*(tilt/TILT_FIELD_SIZE), MAX_VERTICAL_VELOCITY);
			} else {
				verticalVelocity = verticalDirection*Math.max(MAX_VERTICAL_VELOCITY*(tilt/TILT_FIELD_SIZE), -MAX_VERTICAL_VELOCITY);
			}
		} else {
			baseReadingTaken = true;
			baseLine = verticalAngle;
		}
	}
	
	@Override 
	protected boolean notRunnable() {
		return super.notRunnable() || !sensorReadingTaken;
	}
	
	@Override
	public void onEnd() {
		super.onEnd();
		sensorManager.unregisterListener(this);
	}
	
	@Override
	public void onPause() {
		super.onPause();
		sensorManager.unregisterListener(this);
	}
	
	@Override
	public void onResume() {
		Sensor accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		Sensor magnet = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
		baseReadingTaken = false;
		sensorReadingTaken = false;
		sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_GAME);
		sensorManager.registerListener(this, magnet, SensorManager.SENSOR_DELAY_GAME);
		verticalVelocity = 0;
		verticalAngle = 0;
		super.onResume();
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		//Log.d("Cavedroid","onAccuracyChanged: " + sensor.getType() + ", accuracy: " + accuracy);
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
			acceleration = event.values.clone();
		} else {
			magnetic = event.values.clone();
		}
		if (!sensorReadingTaken && acceleration != null && magnetic != null && 
				acceleration[0] != 0 && acceleration[1] != 0 && acceleration[2] != 0) {
			if (SensorManager.getRotationMatrix(rotation, inclination, acceleration, magnetic)) {
				sensorReadingTaken = true;
				synchronized (this) {
					notify();
				}
			}
		}
	}
}
